package org.apache.osgimaker.analyse;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.osgimaker.analyse.algorithm.ClassAttributes;
import org.apache.osgimaker.analyse.algorithm.NameAndSourceAttributes;
import org.apache.osgimaker.analyse.algorithm.graph.AtomicVertex;
import org.apache.osgimaker.analyse.algorithm.graph.NameAttributes;
import org.apache.osgimaker.analyse.algorithm.graph.StrongComponent;
import org.apache.osgimaker.analyse.algorithm.renderer.AbstractStrongComponentRenderer;
import org.apache.osgimaker.analyse.datamodel.PackageInstance;

/**
 * @author Tiger Gui
 * tigergui@gmail.com - Beijing China
 * 
 */
public class AnalyseUtil {
	
	public static String[] getCycleList(StrongComponent[] components){
		List<String> ret = new ArrayList<String>();
		for (int i = 0; i < components.length; i++) {
			StrongComponent cycle = components[i];
			String classList = "";
			for (int j = 0, n = cycle.getNumberOfVertices(); j < n; j++) 
		    {
		      String name = ((NameAttributes) cycle.getVertex(j).getAttributes()).getName();
		      if(j != 0) classList += ",";
		      classList += name;
		    }
			ret.add(classList);
		}
		return ret.toArray(new String[0]);
	}

	/**
	 * 
	 * @param graph
	 * @param cycles
	 * @param layerMap
	 * @return package list info
	 */
	public static List<PackageInstance> getPackageList(AtomicVertex[] graph, StrongComponent[] cycles, Map layerMap){
		List<PackageInstance> packages = new ArrayList<PackageInstance>();
		List list = getTrueCycles(cycles);
		for (int i = 0; i < graph.length; i++) {
			AtomicVertex vertex = graph[i];
			Integer layerIndex = (Integer) layerMap.get(vertex);
			StrongComponent cycle = getCycleFor(vertex, list);
			
			PackageInstance each = new PackageInstance();
			String[] values = new String[10];
		    NameAndSourceAttributes attributes = (NameAndSourceAttributes) vertex.getAttributes();
		    values[0] = attributes.getName();
		    values[2] = Integer.toString(attributes.getSize());
		    values[9] = attributes.getSources();
		    if (attributes instanceof ClassAttributes)
		    {
		      ClassAttributes ca = (ClassAttributes) attributes;
		      values[1] = ca.getType();
		      values[3] = ca.isInnerClass() ? "true" : "false";
		    } else
		    {
		      values[1] = "";
		      values[3] = "";
		    }
		    values[4] = Integer.toString(vertex.getNumberOfIncomingArcs());
		    int usesInternal = 0;
		    int usesExternal = 0;
		    for (int j = 0, n = vertex.getNumberOfOutgoingArcs(); j < n; j++) 
		    {
		      if (((AtomicVertex) vertex.getHeadVertex(j)).isGraphVertex()) 
		      {
		        usesInternal++;
		      } else 
		      {
		        usesExternal++;
		      }
		    }
		    values[5] = Integer.toString(usesInternal);
		    values[6] = Integer.toString(usesExternal);
		    values[7] = Integer.toString(layerIndex);
		    values[8] = cycle == null ? "" 
		                          : AbstractStrongComponentRenderer.createName(cycle); 
		    each.setName(values[0]);
		    each.setCycle(values[8]);
		    each.setLayer(layerIndex);
		    each.setSize(attributes.getSize());
		    each.setSources(values[9]);
		    each.setUsedBy(vertex.getNumberOfIncomingArcs());
		    each.setUsesExternal(usesExternal);
		    each.setUsesInternal(usesInternal);
		    
		    
		    for (int j = 0, n = vertex.getNumberOfIncomingArcs(); j < n; j++) 
		    {
		      String packageName = ((NameAttributes) vertex.getTailVertex(j).getAttributes())
		                  .getName();
		      if(!packageName.trim().equals(each.getName()))
		    	  each.usedByList.add(packageName);
		    }
		    for (int j = 0, n = vertex.getNumberOfOutgoingArcs(); j < n; j++) 
		    {
		      String packageName = ((NameAttributes) vertex.getHeadVertex(j).getAttributes())
		                  .getName();
		      boolean usesType = ((AtomicVertex) vertex.getHeadVertex(j)).isGraphVertex();
		      if(usesType){
		    	  if(!packageName.trim().equals(each.getName()))
		    	  	each.usesInternalList.add(packageName);
		      } 
		      else
		    	  each.usesExternalList.add(packageName);
		    }
		    
		    packages.add(each);
		}
		return packages;
	}
	
	public static List getTrueCycles(StrongComponent[] cycles) {
		List list = new ArrayList();
		if (cycles != null) {
			for (int i = 0; i < cycles.length; i++) {
				if (cycles[i].getNumberOfVertices() > 1) {
					list.add(cycles[i]);
				}
			}
		}
		return list;
	}
	
	public static StrongComponent getCycleFor(AtomicVertex vertex, List cycles) {
		for (int i = 0, n = cycles.size(); i < n; i++) {
			StrongComponent cycle = (StrongComponent) cycles.get(i);
			for (int j = 0, m = cycle.getNumberOfVertices(); j < m; j++) {
				if (cycle.getVertex(j) == vertex) {
					return cycle;
				}
			}
		}
		return null;
	}
}
